/* 
 * File:   Barcode.h
 * Author: alrojas
 *
 * Created on 16 de junio de 2014, 11:23
 */

#ifndef BARCODE_H
#define	BARCODE_H


#include <Magick++.h>
#include <zbar.h>

#include "Utils.h"

using namespace zbar;
using namespace Utils;

namespace Barcode{
    
    /**
     * Localiza la posicion del código de barras.
     * @param src Matriz de entrada.
     * @return Rectangulo que contiene el codigo de barras.
     */
    inline Rect findBarcode(Mat & src){

        Mat gray;
        vector < vector < Point > > contours;
        cvtColor(src,gray,CV_BGR2GRAY);

        threshold(gray,gray,254,255,THRESH_BINARY);
        blur(gray,gray,Size(9,9));
        threshold(gray,gray,31,255,THRESH_BINARY);
       
        findContours(gray,contours,CV_RETR_TREE,CV_CHAIN_APPROX_TC89_L1);

        vector < vector < Point > > contours_poly(contours.size());
        vector < Rect > boundRect(contours.size());
        
        for(uint i = 0; i < contours.size(); i++){ 
            approxPolyDP(Mat(contours[i]),contours_poly[i],3,true);
            boundRect[i] = boundingRect(Mat(contours_poly[i]));
        }
        
        return Rect(boundRect[0].x + 3,boundRect[0].y + 3,boundRect[0].width - 6,boundRect[0].height - 6);
    }
    
    /**
     * Defodifica un codigo de barras.
     * @param src Imagen de entrada. 
     * @param crop Rectangulo que contiene el codigo de barras.
     * @return El contenido del codigo de barras.
     */
    inline string decodeBarcode(Magick::Image & src, Rect crop){ 
        
        // create a reader
        ImageScanner scanner;  
        scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

        src.crop(Magick::Geometry(crop.width,crop.height,crop.x,crop.y));

        // obtain image data
        int width = src.columns();   // extract dimensions
        int height = src.rows();
        Magick::Blob blob;              // extract the raw data
        src.modifyImage();
        src.write(&blob,"GRAY",8);
        const void *raw = blob.data();

        // wrap image data
        Image image(width, height,"Y800",raw, width * height);

        // scan the image for barcodes
        int n = scanner.scan(image);
        
        if (n > 0){
            //extract results
            for(Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
                //  return image.get_data();
                return symbol->get_data();
            }

            image.set_data(NULL,0);
        }

        return "Not Found";
    } 
    
}


#endif	/* BARCODE_H */

